package com.sheepone.util;

import com.sheepone.util.ClassUtil;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author Miss.杨
 * @description
 * @since 2024/2/20 - 16:01
 */
public class ArrayUtil {

    /**
     * 判断两个数组是否有交集
     *
     * @param array1
     * @param array2
     * @return
     */
    public static <T> boolean isIntersecting(T[] array1, T[] array2) {
        if (array1 == null || array2 == null) {
            return false;
        }
        for (T t : array1) {
            for (T t2 : array2) {
                if (t.equals(t2)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static <T> boolean contains(T[] array, T object) {
        if (array == null || object == null) {
            return false;
        }
        for (T t : array) {
            if (t.equals(object)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 移除数组中的指定元素
     *
     * @param nums
     * @param val
     * @return
     */
    public static int removeElement(Object[] nums, Object val) {
        int j = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i].equals(val)) {
                j++;
            }
            if (!nums[i].equals(val) && j != 0) {
                nums[i - j] = nums[i];
            }
        }
        nums = Arrays.copyOf(nums, nums.length - j);
        return nums.length - j;
    }

    /**
     * 给定一个大小为 n 的数组 objects ，返回其中的多数元素。
     * 多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
     *
     * @param objects
     * @return
     */
    public static Object majorityElement(Object[] objects) {
        int count = 0;
        Object candidate = null;

        for (Object object : objects) {
            if (count == 0) {
                candidate = object;
            }
            count += (object.equals(candidate)) ? 1 : -1;
        }

        return count == 0 ? null : candidate;
    }

    /**
     * 给定一个整数数组 array，将数组中的元素向指定方向轮转 k 个位置，其中 k 是非负数。
     * 向右 -> isRight = true; 向左 -> isRight = false;
     *
     * @param array
     * @param k
     * @param isRight
     */
    public static void rotate(Object[] array, int k, boolean isRight) {
        if (isRight) {
            k = array.length - k;
        }
        rotateRightly(array, k);
    }

    private static void rotateRightly(Object[] array, int k) {
        k %= array.length;
        reverse(array, 0, array.length - 1);
        reverse(array, 0, k - 1);
        reverse(array, k, array.length - 1);
    }

    /**
     * 反转数组
     *
     * @param array
     * @param start
     * @param end
     */
    public static void reverse(Object[] array, int start, int end) {
        Object temp;
        while (start < end) {
            temp = array[start];
            array[start] = array[end];
            array[end] = temp;
            start += 1;
            end -= 1;
        }
    }


    public static boolean isEmpty(Object[] array) {
        return array == null || array.length == 0;
    }

    public static double[] subArray(double[] array, int start, int end) {
        // 检查输入参数的有效性
        if (array == null || start < 0 || end >= array.length || start > end) {
            throw new IllegalArgumentException("Invalid array range");
        }

        // 创建一个新的子数组，并复制指定范围内的元素
        int length = end - start + 1;
        double[] subArr = new double[length];
        System.arraycopy(array, start, subArr, 0, length);
        return subArr;
    }

    public static <T> T[] subArray(T[] array, int start, int end) {
        // 检查输入参数的有效性
        if (array == null || start < 0 || end >= array.length || start > end) {
            throw new IllegalArgumentException("Invalid array range");
        }

        // 创建一个新的子数组，并复制指定范围内的元素
        int length = end - start + 1;
        T[] subArr = newArray(ClassUtil.getComponentType(array), length);
        System.arraycopy(array, start, subArr, 0, length);
        return subArr;
    }

    public static <T> T[] newArray(Class<T> clazz, int length) {
        return (T[]) Array.newInstance(clazz, length);
    }

    public static <T> T[] removeDuplicates(T[] objects) {
        if (objects == null || objects.length == 0) {
            return objects;
        }

        Set<T> stringSet = new HashSet<>(Arrays.asList(objects));
        return stringSet.toArray(newArray(ClassUtil.getComponentType(objects), 0));
    }

    public static <T> List<T> removeDuplicates(List<T> objects) {
        if (objects == null || objects.isEmpty()) {
            return objects;
        }

        Set<T> stringSet = new HashSet<>(objects);
        return stringSet.stream().toList();
    }

    public static <E> void swap(E[] elements, int ia, int ib) {
        E temp = elements[ia];
        elements[ia] = elements[ib];
        elements[ib] = temp;
    }
}
